package com.zzyl.nursing.service.impl;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.aliyun.oss.model.ListPartsRequest;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.huaweicloud.sdk.iotda.v5.IoTDAClient;
import com.huaweicloud.sdk.iotda.v5.model.*;
import com.zzyl.common.constant.CacheConstants;
import com.zzyl.common.exception.ServiceException;
import com.zzyl.common.utils.DateUtils;
import com.zzyl.common.utils.bean.BeanUtils;
import com.zzyl.common.utils.uuid.UUID;
import com.zzyl.nursing.dto.DeviceDto;
import com.zzyl.nursing.vo.DeviceDetailVo;
import com.zzyl.nursing.vo.ProductVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.mapper.DeviceMapper;
import com.zzyl.nursing.domain.Device;
import com.zzyl.nursing.service.IDeviceService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

/**
 * 设备表Service业务层处理
 * 
 * @author alexis
 * @date 2025-09-14
 */
@Service
@Slf4j
public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements IDeviceService
{
    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    private IoTDAClient iotDAClient;

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    /**
     * 查询设备表
     * 
     * @param id 设备表主键
     * @return 设备表
     */
    @Override
    public Device selectDeviceById(Long id)
    {
        return deviceMapper.selectById(id);
    }

    /**
     * 查询设备表列表
     * 
     * @param device 设备表
     * @return 设备表
     */
    @Override
    public List<Device> selectDeviceList(Device device)
    {
        return deviceMapper.selectDeviceList(device);
    }

    /**
     * 新增设备表
     * 
     * @param device 设备表
     * @return 结果
     */
    @Override
    public int insertDevice(Device device)
    {
        return deviceMapper.insert(device);
    }

//    /**
//     * 修改设备表
//     *
//     * @param device 设备表
//     * @return 结果
//     */
//    @Override
//    public int updateDevice(Device device)
//    {
//        log.info("开始更新设备，传入设备信息: {}", device);
//        // 1. 基础参数校验
//        if (device == null) {
//            throw new ServiceException("设备信息不能为空");
//        }
//
//        if (device.getId() == null) {
//            throw new ServiceException("设备ID不能为空");
//        }
//
//        // 2. 调用华为云接口更新设备信息
//        try {
//            UpdateDeviceRequest request = new UpdateDeviceRequest();
//            request.setDeviceId(device.getIotId());
//            UpdateDevice body = new UpdateDevice();
//            AuthInfoWithoutSecret authInfobody = new AuthInfoWithoutSecret();
//            authInfobody.withSecureAccess(true);
//            body.withDeviceName(device.getDeviceName());
//            request.withBody(body);
//
//            // 修复：使用正确的变量名 iotDAClient
//            UpdateDeviceResponse response = iotDAClient.updateDevice(request);
//
//            // 检查华为云接口调用结果
//            if (response.getHttpStatusCode() != 200) {
//                throw new ServiceException("更新华为云设备信息失败，状态码：" + response.getHttpStatusCode());
//            }
//        } catch (Exception e) {
//            log.error("调用华为云更新设备接口异常", e);
//            throw new ServiceException("更新设备到华为云平台失败：" + e.getMessage());
//        }
//
//        // 3. 更新本地数据库中的设备信息
//        Device existingDevice = deviceMapper.selectById(device.getId());
//        if (existingDevice == null) {
//            throw new ServiceException("设备不存在");
//        }
//
//        // 安全更新字段
//
//        if (device.getBindingLocation() != null) {
//            existingDevice.setBindingLocation(device.getBindingLocation());
//        }
//        if (device.getDeviceDescription() != null) {
//            existingDevice.setDeviceDescription(device.getDeviceDescription());
//        }
//
//        // 处理位置类型和物理位置类型的更新
//        if (device.getLocationType() != null) {
//            existingDevice.setLocationType(device.getLocationType());
//            // 如果是随身设备(0)，设置物理位置类型为-1
//            if (device.getLocationType() == 0) {
//                existingDevice.setPhysicalLocationType(-1);
//                existingDevice.setRemark(device.getRemark());
//            }
//        }
//
//        if (device.getPhysicalLocationType() != null) {
//            existingDevice.setPhysicalLocationType(device.getPhysicalLocationType());
//            // 如果物理位置类型为-1，设置为随身设备
//            if (device.getPhysicalLocationType() == -1) {
//                existingDevice.setLocationType(0);
//            } else {
//                // 如果物理位置类型不为-1，设置为固定设备
//                existingDevice.setLocationType(1);
//                existingDevice.setRemark(device.getRemark());
//            }
//        }
//
//        if(device.getDeviceName() != null){
//            existingDevice.setDeviceName(device.getDeviceName());
//        }
//        if(device.getRemark() != null){
//            existingDevice.setRemark(device.getRemark());
//        }
//        return deviceMapper.updateById(existingDevice);
//    }




    /**
     * 删除设备表信息
     * 
     * @param iotId 设备表主键
     * @return 结果
     */
    @Override
    public int deleteDeviceById(String iotId) {
        log.info("开始删除设备，传入设备IoT ID: {}", iotId);

        if (iotId == null || iotId.isEmpty()) {
            throw new ServiceException("设备IoT ID不能为空");
        }

        // 1. 通过IoT ID查询设备信息
        Device device = deviceMapper.selectOne(new LambdaQueryWrapper<Device>()
                .eq(Device::getIotId, iotId));

        if (device == null) {
            log.warn("设备不存在，IoT ID: {}", iotId);
            throw new ServiceException("设备不存在");
        }

        log.info("找到要删除的设备: {}", device);

        // 2. 调用华为云接口删除设备（如果需要的话）
        try {
            DeleteDeviceRequest request = new DeleteDeviceRequest();
            request.setDeviceId(iotId);
            DeleteDeviceResponse response = iotDAClient.deleteDevice(request);
            log.info("删除华为云设备响应: {}", response);

            if (response.getHttpStatusCode() != 204) {
                log.warn("删除华为云设备可能失败，状态码: {}", response.getHttpStatusCode());
            }
        } catch (Exception e) {
            log.error("调用华为云删除设备接口异常", e);
            // 根据业务需求决定是否继续删除本地数据
        }

        // 3. 删除本地数据库中的设备记录（使用数据库主键ID）

        return deviceMapper.deleteById(device.getId());
    }

    /**
     * 同步产品列表存入redis
     */
    @Override
    public void syncProductList() {

        ListProductsRequest request = new ListProductsRequest();
        request.setLimit(50);
        ListProductsResponse response = iotDAClient.listProducts(request);
        log.info("同步产品结束，返回结果:{}", response);
        int code = response.getHttpStatusCode();
        if (code != 200) {
            throw new RuntimeException("同步产品失败!");
        }
        List<ProductSummary> products=response.getProducts();
        //存入redis
        redisTemplate.opsForValue().set(CacheConstants.IOT_PLATFORM_DEVICE, JSONUtil.toJsonStr(products));

    }

    /**
     * 同步产品从redis取出
     * @return
     */
    @Override
    public List<ProductVo> allProduct() {
        String jsonStr = (String) redisTemplate.opsForValue().get(CacheConstants.IOT_PLATFORM_DEVICE);
        if (StrUtil.isEmpty(jsonStr)){
            return new ArrayList<>();
        }
        List<ProductVo> list = JSONUtil.toList(jsonStr, ProductVo.class);
        return list;
    }

    /**
     * 注册设备
     * @param dto
     */
    @Override
    public void register(DeviceDto dto) {
        //位置类型为0随身设备时，设置物理位置类型为-1
        if (dto.getLocationType()==0){
            dto.setDeviceDescription(String.valueOf(dto.getBindingLocation()));
            dto.setPhysicalLocationType(-1);
        }
        //1.判断设备名称是否已经重复 deviceName
        LambdaQueryWrapper<Device> qw = new LambdaQueryWrapper<>();
        qw.eq(Device::getDeviceName,dto.getDeviceName());
        Device device = deviceMapper.selectOne(qw);
        if(device != null){
            throw new RuntimeException("设备名称重复");
        }
        //2.检验设备标识是否已经重复
        LambdaQueryWrapper<Device> nodeIdQueryWrapper = new LambdaQueryWrapper<>();
        nodeIdQueryWrapper.eq(Device::getIotId, dto.getIotId());
        Device deviceByNodeId = deviceMapper.selectOne(nodeIdQueryWrapper);
        if (Objects.nonNull(deviceByNodeId)) {
            throw new RuntimeException("设备标识重复");
        }
        //3.校验同一位置是否绑定了同一类产品【数据库有唯一约束，可以走异常处理器】
        Device device1 = deviceMapper.selectOne(new LambdaQueryWrapper<Device>()
                .eq(Device::getBindingLocation, dto.getBindingLocation())
                .eq(Device::getProductKey, dto.getProductKey())
                .eq(Device::getLocationType, dto.getLocationType())
                .eq(Device::getPhysicalLocationType, dto.getPhysicalLocationType()));
        if (device1 != null) {
            throw new RuntimeException("同一位置已绑定该类产品，无法重复绑定");
        }


        //4.调用华为云的SDK，向华为云的IoT中新增设备
        AddDeviceRequest request = new AddDeviceRequest();
        AddDevice body = new AddDevice();
        //产品ID
        body.withProductId(dto.getProductKey());
        //设备名称
        body.withDeviceName(dto.getDeviceName());
        //设备标识码
        body.withNodeId(dto.getNodeId());
        //请求体
        request.withBody(body);
        //设备密钥
        AuthInfo authInfo = new AuthInfo();
        String secret = UUID.randomUUID().toString().replaceAll("-", "");
        //设置密钥
        authInfo.withSecret(secret);
        body.setAuthInfo(authInfo);

        request.withBody(body);
        //调用华为云接口
        AddDeviceResponse response = null;
        try {
            response = iotDAClient.addDevice(request);


        } catch (Exception e) {
            throw new ServiceException("注册设备失败,网络异常");
        }
        //判断状态码
        int code = response.getHttpStatusCode();
        if(code != 201){
            throw new RuntimeException("注册设备失败");
        }
        //5.保存数据到数据库
         device = new Device();
        //属性复制
        BeanUtils.copyBeanProp(device,dto);
        //设备标识码
        device.setIotId(response.getDeviceId());
        //设备密钥
        device.setSecret(secret);
        //设备标识符iotid
        device.setNodeId(dto.getNodeId());
        deviceMapper.insert(device);

    }

    /**
     * 获取设备详情
     * @param iotId 设备标识码
     * @return 设备详情
     */
    @Override
    public DeviceDetailVo getDeviceDetail(String iotId) {
        if (iotId == null){
            throw new RuntimeException("设备标识码不能为空");
        }
        DeviceDetailVo deviceDetailVo = new DeviceDetailVo();
        //查询华为云iot的设备数据
        ShowDeviceRequest request = new ShowDeviceRequest();
        request.withDeviceId(String.valueOf(iotId));
        try {
            ShowDeviceResponse response = iotDAClient.showDevice(request);
            if (response.getHttpStatusCode() == 200){
                deviceDetailVo.setDeviceStatus(response.getStatus());
                if (StrUtil.isNotEmpty(response.getActiveTime())){
                    deviceDetailVo.setActiveTime(LocalDateTime.parse(response.getActiveTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("获取设备详情失败");
        }
        //查询数据库的设备数据
        Device device = deviceMapper.selectOne(new LambdaQueryWrapper<Device>()
                .eq(Device::getIotId, iotId));
        if (device == null){
            throw new RuntimeException("设备不存在");
        }
        BeanUtils.copyBeanProp(deviceDetailVo,device);
        return deviceDetailVo;
    }

    /**
     * 查询设备上报服务属性
     * @param iotId 设备 ID
     * @return 设备服务属性
     */
    @Override
    public List<Map<String, Object>> queryServiceProperties(String iotId) {
        if (iotId == null){
            throw  new ServiceException("设备标识码不能为空");
        }
        //创建查询设备服务属性的请求
        ShowDeviceShadowRequest request = new ShowDeviceShadowRequest();
        //设备标识码
        request.withDeviceId(iotId);
        // 发送请求并获取响应
        ShowDeviceShadowResponse response = iotDAClient.showDeviceShadow(request);
        if (response.getHttpStatusCode() != 200){
            throw new ServiceException("查询设备服务属性失败");
        }
        List<DeviceShadowData> shadow = response.getShadow();
        if (CollectionUtil.isNotEmpty(shadow)) {
            DeviceShadowProperties reported= shadow.get(0).getReported();
            //处理上报时间日期
            LocalDateTime activeTime =  LocalDateTimeUtil.parse(shadow.get(0).getReported().getEventTime(), "yyyyMMdd'T'HHmmss'Z'");
            //日期时区转换
            LocalDateTime eventTime = activeTime.atZone(ZoneId.from(ZoneOffset.UTC))
                    .withZoneSameInstant(ZoneId.of("Asia/Shanghai"))
                    .toLocalDateTime();

//            String eventTime = reported.getEventTime();
            Map<String, Object> properties = (Map<String,Object>) reported.getProperties();
            if (CollectionUtil.isNotEmpty( properties)){
                List collect = properties.entrySet().stream().map((Function<Map.Entry, Map>) entry -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("functionId", entry.getKey());
                    map.put("value", entry.getValue());
                    map.put("eventTime", eventTime);
                    return map;

                }).collect(Collectors.toList());
                return collect;
            }
        }
        return List.of();

    }

    /**
     * 修改设备信息
     * @param dto
     */
    @Override
    public void editDevice(DeviceDto dto) {
        UpdateDeviceRequest request = new UpdateDeviceRequest();
        request.withDeviceId(dto.getIotId());
        UpdateDevice body = new UpdateDevice();
        AuthInfoWithoutSecret authInfobody = new AuthInfoWithoutSecret();
        authInfobody.withSecureAccess(true);
        body.withAuthInfo(authInfobody);
        body.withDeviceName(dto.getDeviceName());
        request.withBody(body);
        UpdateDeviceResponse updateDeviceResponse = iotDAClient.updateDevice(request);
        if(updateDeviceResponse.getHttpStatusCode() != 200){
            throw new ServiceException("设备修改失败！");
        }

        //位置类型为0随身设备时，设置物理位置类型为 -1
        if(dto.getLocationType() == 0){
            dto.setDeviceDescription( String.valueOf(dto.getBindingLocation()) );
            dto.setPhysicalLocationType(-1);
        }
        dto.setRemark(dto.getRemark());
        Device device = new Device();
        BeanUtils.copyBeanProp(device, dto);
        deviceMapper.updateDevice(device);
    }

    @Override
    public List<ServiceCapability> queryProduct(String productKey) {
        ShowProductRequest request = new ShowProductRequest();
        request.withProductId(productKey);
        ShowProductResponse response = iotDAClient.showProduct(request);
        if (response.getHttpStatusCode() == 200){
            return response.getServiceCapabilities();
        }
        return null;
    }

    /**
     * 获取设备绑定的老人护工
     * @param iotId 设备 ID
     * @return
     */
    @Override
    public List<Long> getNursingIdsByIotId(String iotId) {
        return deviceMapper.selectNursingIdsByIotId(iotId);
    }


}
